home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr05
/
xnot12a.zip
/
W3IO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-11
|
11KB
|
513 lines
#ifdef MSW /** WHOLE FILE **/
/* Munged code from ttyio, changed as needed to interface to Windows
* and pretend to be a terminal window. This was early porting work and
* shows it; I took the existing code and just hacked it to work. Some
* new functions were added if they felt like they belonged in this file.
*
* NOTE that for Windows I created a routine (ttputline) and turned
* off the GOSLING code. Much less compute intensive, and on my 486
* I get much better performance just redrawing everything as opposed to
* trying to figure out which lines of the screen can be moved, moving them
* and redrawing around the moved lines. Define GOSLING if you want (see
* ttydef.h) to see which runs best on your system. There is code in here
* to support either option.
*/
#include "jam.h"
/*
* Window 3.1 interface
*/
#include "def.h"
int tceeol = 0 /* 2 */; /* very cheap */
int tcinsl = 2 /* 5 */;
int tcdell = 2 /* 5 */;
static int bioscol = -1; /* cursor column */
static int curcolor = -1;
#ifdef GOSLING
static void WindowMoveLines(int row, int bot, int num, int up);
#endif
static void rn_(putthechar,(unsigned char c));
/* Erase window content
*/
void WindowErase(void)
{
RECT rect;
if (edInited)
{
GetClientRect(g_hWnd, &rect);
ZapRect(&rect);
curcolor = -1; /* force refresh rechecks system colors */
}
}
/*
* Initialize the terminal when the editor
* gets started up.
*/
ttinit()
{
/* if notGNU were windows-aware, it would
* do something here
*/
return TRUE;
}
/*
* Clean up the terminal, in anticipation of
* a return to the command interpreter.
*/
tttidy()
{
return TRUE;
}
/*
* Move the cursor to the specified
* origin 0 row and column position.
*/
ttmove(int row, int col)
{
ttcol = col;
ttrow = row;
g_caret_x = col * g_nCharWidth;
g_caret_y = row * g_nLineHeight;
/* make cursor up-to-date
*/
#ifdef WINDOWS_CURSOR
SetCaretPos(g_caret_x, g_caret_y);
#endif
bioscol = col;
return TRUE;
}
/*
* Erase to end of page.
*/
tteeop()
{
if (edInited)
WindowZapLines(ttrow, nrow);
return TRUE;
}
/* Generic fill-to-background function
*/
void WindowZapLines(int row, int bot)
{
RECT rect;
GetClientRect(g_hWnd, &rect);
rect.top = row * g_nLineHeight;
rect.bottom = ((bot + 1) * g_nLineHeight) - 1;
ZapRect(&rect);
}
/*
* Insert nchunk blank line(s) onto the
* screen, scrolling the last line on the
* screen off the bottom.
*/
ttinsl(int row, int bot, int nchunk)
{
#ifdef GOSLING
if (row == bot)
{ /* Case of one line insert is */
ttmove(row, 0); /* special */
tteeol();
}
else
WindowMoveLines(row, bot, nchunk, FALSE);
#endif
return TRUE;
}
/*
* Delete nchunk line(s) from "row", replacing the
* bottom line on the screen with a blank line.
*/
ttdell(int row, int bot, int nchunk)
{
#ifdef GOSLING
if (row == bot)
{ /* One line special case */
ttmove(row, 0);
tteeol();
}
else
WindowMoveLines(row, bot, nchunk, TRUE);
#endif
return TRUE;
}
/*
* Switch to full screen scroll. This is
* used by "spawn.c" just before is suspends the
* editor, and by "display.c" when it is getting ready
* to exit.
*/
ttnowindow()
{
return TRUE;
}
/*
* Set the current writing color to the
* specified color. Watch for color changes that are
* not going to do anything (the color is already right)
* and don't send anything to the display.
*
* This code and text output in this file can ONLY work
* if this is the only place color is set!
*
*/
ttcolor(color)
register int color;
{
if (curcolor != color)
{
curcolor = color;
if (color == CTEXT)
{
SetBkColor(g_hDC, GetBackColor());
SetTextColor(g_hDC, GetForeColor());
}
else if (color == CMODE)
{
SetBkColor(g_hDC, GetForeColor());
SetTextColor(g_hDC, GetBackColor());
}
else if (curcolor == CHIGH)
{
SetBkColor(g_hDC, GetBackColor());
SetTextColor(g_hDC, GetHighColor());
}
}
tthue = color; /* Save the color. */
return TRUE;
}
/*
* This routine is called by the
* "refresh the screen" command to try and resize
* the display. The new size, which must be deadstopped
* to not exceed the NROW and NCOL limits, it stored
* back into "nrow" and "ncol". Display can always deal
* with a screen NROW by NCOL. Look in "window.c" to
* see how the caller deals with a change.
*/
ttresize()
{
int flag = 0;
setttysize();
if (nrow > NROW)
flag = nrow = NROW;
if (ncol > NCOL)
flag = ncol = NCOL;
/* non-zero means reached a limit
*/
if (flag)
WindowMessage("Internal limit: max rows/cols reached.", FALSE);
return TRUE;
}
ttputc(c)
unsigned char c;
{
if (c == '\b') /* odd the way this works.. */
{
if (bioscol-1 > 0)
{
ttmove(ttrow, bioscol-1);
}
return(1);
}
else if (c == '\r') /* this too... */
{
ttmove(ttrow, 0);
return(1);
}
if (edInited)
putthechar(c);
if (bioscol + 1 >= ncol)
ttmove(ttrow + 1, 0);
else
ttmove(ttrow, bioscol + 1);
return(TRUE);
}
/*
* Erase to end of line.
*/
tteeol()
{
RECT rect;
if (edInited)
{
GetClientRect(g_hWnd, &rect);
rect.top = g_caret_y;
rect.left = g_caret_x;
rect.bottom = rect.top + g_nLineHeight;
ZapRect(&rect);
}
return TRUE;
}
/*
* Make a noise.
*/
ttbeep()
{
MessageBeep((UINT)-1);
return TRUE;
}
/* Insert/delete num lines at row
*/
#ifdef GOSLING
static void WindowMoveLines(int row, int bot, int num, int up)
{
RECT scrollrect, clearrect;
int line, direction;
if (up)
{
direction = -1;
line = bot;
}
else /* down */
{
direction = 1;
line = row;
}
/* Load rect with window size (inside the borders, menubar, etc)
*/
GetClientRect(g_hWnd, &scrollrect);
/* Reset height for target rows
*/
scrollrect.top = row * g_nLineHeight;
scrollrect.bottom = (bot + 1) * g_nLineHeight;
ScrollWindowEx(g_hWnd, 0, (num * g_nLineHeight) * direction,
&scrollrect, &scrollrect, 0, &clearrect, 0);
WindowZapLines(line, line);
ZapRect(&clearrect);
}
#endif
/* Dump char to screen (window); mostly only for echo line
*/
#define LINESIZE (NCOL + 2)
static char theLine[LINESIZE];
static int theX, theY;
static int theColor;
static int theIndex = 0;
static void putthechar(unsigned char c)
{
/* Flush text if buffer fills, color changes or position
* of new char is not directly following last char, on same line.
*/
if ((theIndex + 1) >= LINESIZE)
ttcharflush();
else if (curcolor != theColor)
ttcharflush();
else if ((theX + (theIndex * g_nCharWidth)) != g_caret_x)
ttcharflush();
else if (theY != g_caret_y)
ttcharflush();
/* Add new char to string.
*/
if (theIndex == 0) /* Save the start position, etc of new line */
{
theColor = curcolor;
theX = g_caret_x;
theY = g_caret_y;
}
theLine[theIndex++] = (char)c;
theLine[theIndex] = '\0';
}
/* Dump whole line of text; called by redisplay code
* and alternate echo (msg line) code
*/
int ttputline(text)
char *text;
{
int len = strlen(text);
#if 0 /* this code seems unneccessary, and is probably slower */
RECT rect;
if (len)
{
rect.left = g_caret_x;
rect.top = g_caret_y;
rect.right = g_nCharWidth * ncol; /* window will clip */
rect.bottom = rect.top + g_nLineHeight;
ExtTextOut(g_hDC, g_caret_x, g_caret_y, ETO_OPAQUE, &rect, text, len,
NULL);
}
#else
if (len)
ExtTextOut(g_hDC, g_caret_x, g_caret_y, 0, 0, text, len, NULL);
#endif
return(TRUE);
}
ttwait()
{
return(0); /* nothing to wait for */
}
/* Not perfectly nice, but ok. We know we have timer msgs
* coming in every so often, so just count them out. Other
* messages (key presses) will be waiting for us in the input queue, so
* nothing is lost. Actually, except for the (sigh) input loop here vs
* the 'real' loop in w3win.c, this is kinda alright.
*/
void sleep(int amount)
{
MSG msg;
int incs = 0;
for (; g_idTimer && (amount > 0); )
{
if (GetMessage(&msg, 0, WM_TIMER, WM_TIMER))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
incs++;
/* how many secs?
*/
if (incs == (INCS_PER_SLEEP)) /* if this is too big, we seem to hang */
{
amount--;
incs = 0;
}
}
}
}
/* Erase a given rect
*/
void ZapRect(RECT *rect)
{
HBRUSH hbrush;
COLORREF color = GetBackColor();
hbrush = CreateSolidBrush(color);
FillRect(g_hDC, rect, hbrush);
DeleteObject(hbrush);
}
/* Query for window size and convert it to
* rows and cols based on current font info
*/
void WindowGetSize(int *nrow, int *ncol)
{
RECT rect;
int width, height;
if (!IsIconic(g_hWnd))
{
GetClientRect(g_hWnd, &rect);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
*ncol = width/g_nCharWidth;
*nrow = height/g_nLineHeight;
}
else
{
*ncol = START_COLS;
*nrow = START_LINES;
}
}
void WindowNewSize(row,col)
int row,col;
{
RECT rect;
GetWindowRect(g_hWnd, &rect);
SizeWindow(rect.left, rect.top, col, row);
}
/* (Re)size the window based on cols & rows
*/
void SizeWindow(int x, int y, int cols, int lines)
{
int menu = 0;
if (g_menu)
menu = GetSystemMetrics(SM_CYMENU);
MoveWindow(g_hWnd, x, y,
(g_nCharWidth * cols) + (2 * GetSystemMetrics(SM_CXFRAME))
#ifdef VBAR
+ GetSystemMetrics(SM_CXVSCROLL)
#endif
,
(g_nLineHeight * lines) + (2 * GetSystemMetrics(SM_CYFRAME)) +
menu + GetSystemMetrics(SM_CYCAPTION), TRUE);
}
/* Draw marker based on cursor location; for drag select only.
* Must be xor!
*/
void DrawMarker()
{
RECT rect;
BOOL wasVis = IsCaretVis();
if (wasVis)
SetCaretVis(FALSE);
rect.left = g_caret_x;
rect.top = g_caret_y;
rect.bottom = rect.top + g_nLineHeight;
rect.right = rect.left + g_nCharWidth;
InvertRect(g_hDC, &rect);
if (wasVis)
SetCaretVis(TRUE);
}
void WindowSync()
{
/* noop on Win 3.1 */
}
void WindowFlush()
{
ttcharflush(); /* possible cached output chars */
/* no other Windows thing needed */
}
/* Flush any output, clear the string
*/
void ttcharflush()
{
if (theIndex >= 1)
{
int save_curcolor = curcolor;
ttcolor(theColor);
ExtTextOut(g_hDC, theX, theY, 0, 0, theLine, strlen(theLine), NULL);
ttcolor(save_curcolor);
theLine[0] = '\0';
theIndex = 0;
}
}
#endif /* WHOLE FILE */